今天是第 26 天 !!!
我們將會透過 Recurrent Neural Network (RNN) 和 Long Short-Term Memory (LSTM) 來對銷售額進行預測。
Kaggle Competition 是 Store Sales - Time Series Forecasting
資料集包括日期、商店和產品信息,以及該產品是否正在促銷,以及銷售數字。
train.csv
包括時間序列特徵store_nbr
、family
和 onpromotion
,以及目標銷售。
store_nbr
: 識別出售產品的商店。family
: 識別出售的產品類型。sales
給出了在特定日期的特定商店中產品家族的總銷售額。test.csv
具有與訓練數據相同的特徵。
預測此文件中日期的目標銷售額。
測試資料中的日期是訓練數據中最後日期之後的15天。
stores.csv
商店,包括城市、州、類型和集群。其中,cluster是相似商店的分組。
oil.csv
每日油價。包括在訓練和測試數據時間範圍內的數值。
holidays_events.csv
節假日和活動
import os
import numpy as np # 線性代數
import pandas as pd # 數據處理,CSV文件輸入/輸出(例如pd.read_csv)
from sklearn import preprocessing # 使用scikit-learn進行數據預處理
from sklearn.preprocessing import MinMaxScaler # 使用MinMaxScaler進行特徵縮放
from sklearn.preprocessing import OrdinalEncoder # 使用OrdinalEncoder對特徵進行編碼
import tensorflow as tf # 引入TensorFlow深度學習庫
from tensorflow import keras # 引入Keras,作為TensorFlow的高階API
from tensorflow.keras import layers # 引入Keras的各種層
from tensorflow.keras.layers import SimpleRNN, LSTM, Dense # 引入RNN、LSTM和Dense層
from tensorflow.keras.layers import Dropout # 引入Dropout層,用於防止過擬合
from tensorflow.keras.layers import Reshape # 引入Reshape層,用於重塑輸出形狀
from tensorflow.keras.models import Model # 引入Keras模型
from tensorflow.keras.optimizers import Adam # 引入Adam優化器,用於模型訓練
from tensorflow.keras.layers import BatchNormalization # 引入BatchNormalization層,用於規範輸入數據
import warnings
warnings.filterwarnings('ignore') # 忽略警告訊息
data_path = '../input/store-sales-time-series-forecasting/'
# 讀取oil.csv文件,並將'date'列設置為索引
oil = pd.read_csv(os.path.join(data_path, 'oil.csv'), index_col='date')
# 讀取holidays_events.csv文件,並將'date'列設置為索引
holidays_events = pd.read_csv(os.path.join(data_path, 'holidays_events.csv'), index_col='date')
# 讀取stores.csv文件
stores = pd.read_csv(os.path.join(data_path, 'stores.csv'))
# 讀取transactions.csv文件
transactions = pd.read_csv(os.path.join(data_path, 'transactions.csv'))
# 讀取train.csv文件,將'id'列設置為索引,並解析'date'列為日期格式
train = pd.read_csv(os.path.join(data_path, 'train.csv'), index_col='id', parse_dates=['date'], infer_datetime_format=True)
# 讀取test.csv文件,並解析'date'列為日期格式
test = pd.read_csv(os.path.join(data_path, 'test.csv'), parse_dates=['date'], infer_datetime_format=True)
keras.backend.clear_session()
np.random.seed(42)
tf.random.set_seed(42)
def timemodel():
model = keras.Sequential()
### basic RNN model
model.add(layers.SimpleRNN(units=200, return_sequences=True, input_shape=[n_past, n_features]))
model.add(keras.layers.BatchNormalization())
model.add(layers.Dropout(0.2))
model.add(layers.SimpleRNN(units=200, return_sequences=True))
model.add(keras.layers.BatchNormalization())
model.add(layers.Dropout(0.2))
model.add(keras.layers.TimeDistributed(keras.layers.Dense(n_features)))
model.compile(loss="mae", optimizer=keras.optimizers.Adam(learning_rate=0.001), metrics=['mae'])
return model
這裡我們建立了一個基本的時間序列模型。
該模型包括兩個SimpleRNN層,每個層都包含200個單元,並使用批次正規化和丟棄層進行規範和防止過擬合。
最後,模型使用TimeDistributed對Dense層進行時間分佈,然後使用均方誤差(MAE)作為損失函數,Adam優化器進行訓練,學習率為0.001,同時計算MAE指標。
Model: "sequential"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
simple_rnn (SimpleRNN) (None, 16, 200) 396600
_________________________________________________________________
batch_normalization (BatchNo (None, 16, 200) 800
_________________________________________________________________
dropout (Dropout) (None, 16, 200) 0
_________________________________________________________________
simple_rnn_1 (SimpleRNN) (None, 16, 200) 80200
_________________________________________________________________
batch_normalization_1 (Batch (None, 16, 200) 800
_________________________________________________________________
dropout_1 (Dropout) (None, 16, 200) 0
_________________________________________________________________
time_distributed (TimeDistri (None, 16, 1782) 358182
=================================================================
Total params: 836,582
Trainable params: 835,782
Non-trainable params: 800
_________________________________________________________________
early_stopping = keras.callbacks.EarlyStopping(monitor = 'val_mae',
min_delta=0.0001,
patience=100,
restore_best_weights=True)
EPOCHS = 1000
model_history = model.fit(
X_train, y_train,
validation_data=(X_val, y_val),
epochs=EPOCHS,
callbacks=[early_stopping],
batch_size=512,
shuffle=True)
這裡使用提前停止回調函數來訓練模型。
該回調函數將監控驗證集上的均方誤差(val_mae),如果均方誤差的變化小於0.0001,並且在連續100個epoch內未改善模型性能,則提前停止訓練,並還原最佳權重。
訓練總共執行1000個epoch,並使用批次大小為512,同時對訓練數據進行洗牌。
for day_ith, day_ith_pred in y_predict.iterrows():
# 對於每一天的每個樣本數量(從0到1781,對應16天)
for n_samples_per_day in range(len(day_ith_pred)):
# 獲取樣本的ID
sample_id = pivoted_test.iloc[[day_ith], [n_samples_per_day]].values[0][0] # 總樣本數
# 將預測值設為非負值(如果預測值為負數,則設為0)
values = max(0, day_ith_pred.values[n_samples_per_day])
# 將預測的銷售值存儲在submission數據框中
submission.at[sample_id, 'sales'] = values
將模型預測的結果(y_predict
)映射到測試數據中(pivoted_test
),並將預測的銷售值存儲在submission數據框中。
完整的 code 可以去 Kaggle Notebook 實際執行喔~
接下來幾天將進入最後一個主題 Reinforcement Learning !!!
敬請期待 ~